/*
 * Copyright 2010-2011 Mike Novak <michael.novakjr@gmail.com>
 * Copyright 2010 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.codeversed.plugins.buzz.oauth;

import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Display;
import android.view.ViewGroup;
import android.view.Window;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.exception.OAuthMessageSignerException;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthProvider;

import java.lang.ref.WeakReference;
import java.net.URLEncoder;

import com.codeversed.plugins.buzz.R;
import com.codeversed.plugins.buzz.util.Constants;
import com.codeversed.plugins.buzz.util.HttpUtils;

public class BuzzDialog extends Dialog {
    private static final String OAUTH_TOKEN_REQUEST = "https://www.google.com/accounts/OAuthGetRequestToken";
    private static final String OAUTH_AUTH_REQUEST = "https://www.google.com/buzz/api/auth/OAuthAuthorizeToken";
    private static final String OAUTH_ACCESS_REQUEST = "https://www.google.com/accounts/OAuthGetAccessToken";
    
    public static final int STATUS_OK = 0x1;
    public static final int STATUS_FAILED = 0x2;
    
	private DialogListener mListener;
	private LinearLayout mContent;
	private ProgressDialog mSpinner;
	private TextView mTitle;
	private WebView mWebView;
	
	private Handler mHandler = new Handler();
	private OAuthConsumer mConsumer;
	private OAuthProvider mProvider;
	
	static final int MARGIN = 4;
	static final int PADDING = 2;
	static final int BUZZ_RED = 0xFF0000;
	
	static final float[] DIMENS_PORT = {280, 420};
	static final float[] DIMENS_LAND = {460, 260};
	
	static final FrameLayout.LayoutParams FILL = 
		new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, 
			ViewGroup.LayoutParams.FILL_PARENT);
	
	public BuzzDialog(Context context, DialogListener listener) {
		super(context);
		mListener = listener;
	}
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mSpinner = new ProgressDialog(getContext());
		mSpinner.requestWindowFeature(Window.FEATURE_NO_TITLE);
		mSpinner.setMessage(getContext().getString(R.string.loading));
		
		mContent = new LinearLayout(getContext());
		mContent.setOrientation(LinearLayout.VERTICAL);
		
		mConsumer = new CommonsHttpOAuthConsumer("anonymous", "anonymous");
        mProvider = new CommonsHttpOAuthProvider(OAUTH_TOKEN_REQUEST + "?scope=" + 
                URLEncoder.encode("https://www.googleapis.com/auth/buzz") + "&xoauth_displayname=" +
                URLEncoder.encode("Buzz for SlideScreen"), OAUTH_ACCESS_REQUEST, OAUTH_AUTH_REQUEST);
		
		setupTitle();
		setupWebView();
		
		Display display = getWindow().getWindowManager().getDefaultDisplay();
		final float scale = getContext().getResources().getDisplayMetrics().density;
		float[] dimens = (display.getWidth() < display.getHeight()) ? DIMENS_PORT : DIMENS_LAND;
		
		addContentView(mContent, new FrameLayout.LayoutParams((int) (dimens[0] * scale + 0.5f),
			(int) (dimens[1] * scale + 0.5f)));			
	}
	
	public void onAttachedToWindow() {
	    mSpinner.show();
	}
	
	private void setupTitle() {
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		
		Drawable icon = getContext().getResources().getDrawable(R.drawable.ic_dialog_title_buzz);
		
		mTitle = new TextView(getContext());
		mTitle.setText("Google Buzz");
		mTitle.setTextColor(Color.WHITE);
		mTitle.setTypeface(Typeface.DEFAULT_BOLD);
		mTitle.setBackgroundColor(BUZZ_RED);
		mTitle.setPadding(MARGIN + PADDING, MARGIN, MARGIN, MARGIN);
		mTitle.setCompoundDrawablePadding(MARGIN + PADDING);
		mTitle.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
		
		mContent.addView(mTitle);
	}
	
	private void setupWebView() {
		mWebView = new WebView(getContext());
		mWebView.setVerticalScrollBarEnabled(false);
		mWebView.setHorizontalScrollBarEnabled(false);
		mWebView.setWebViewClient(new BuzzDialog.BuzzWebViewClient());
		mWebView.getSettings().setJavaScriptEnabled(true);
		mWebView.setLayoutParams(FILL);
		
		AuthorizeTokenTask task = new AuthorizeTokenTask(mWebView, mConsumer, mProvider);
		task.execute();
		
		mContent.addView(mWebView);
	}
	
	class AuthorizeTokenTask extends AsyncTask<String, Void, String> {
	    WeakReference<WebView> mWebViewRef;
	    WeakReference<OAuthConsumer> mConsumerRef;
	    WeakReference<OAuthProvider> mProviderRef;
	    
	    public AuthorizeTokenTask(WebView view, OAuthConsumer consumer, OAuthProvider provider) {
	        mWebViewRef = new WeakReference<WebView>(view);
	        mConsumerRef = new WeakReference<OAuthConsumer>(consumer);
	        mProviderRef = new WeakReference<OAuthProvider>(provider);
	    }
	    
	    @Override
	    protected String doInBackground(String... params) {
	        StringBuilder sb = new StringBuilder();
	        
	        try {
	            String url = mProviderRef.get().retrieveRequestToken(mConsumerRef.get(), "http://slidescreenbuzz.com/callback");
	            sb.append(url);
	            sb.append("&btmpl=mobile&scope=");
	            sb.append(URLEncoder.encode("https://www.googleapis.com/auth/buzz"));
	            sb.append("&domain=anonymous");
	            sb.append("&xoauth_displayname=");
	            sb.append(URLEncoder.encode("Buzz for SlideScreen"));
	            sb.append("&iconUrl=");
	            sb.append(URLEncoder.encode("http://quietlycoding.com/buzz.png"));
	            
	            return sb.toString();
	        } catch (Exception e) {
	            Log.e(Constants.LOG_TAG, "Error retrieving request token: " + e.toString());
	            return null;
	        }
	    }
	    
	    @Override
	    protected void onPostExecute(String url) {
	        if (url != null) {
	            mWebViewRef.get().loadUrl(url);
            }
            
            /* TODO: probably a good idea to show an error message. */
	    }
	}
	
	class AccessTokenTask extends AsyncTask<String, Void, Integer> {
	    WeakReference<Dialog> mDialogRef;
	    WeakReference<ProgressDialog> mSpinnerRef;
	    WeakReference<OAuthConsumer> mConsumerRef;
	    WeakReference<OAuthProvider> mProviderRef;
	    WeakReference<BuzzDialog.DialogListener> mListenerRef;
	    WeakReference<WebView> mWebViewRef;
	    
	    public AccessTokenTask(Dialog dialog, WebView view, ProgressDialog spinner, OAuthConsumer consumer, OAuthProvider provider) {
	        mDialogRef = new WeakReference<Dialog>(dialog);
	        mSpinnerRef = new WeakReference<ProgressDialog>(spinner);
	        mConsumerRef = new WeakReference<OAuthConsumer>(consumer);
	        mProviderRef = new WeakReference<OAuthProvider>(provider);
	        mWebViewRef = new WeakReference<WebView>(view);
	    }
	    
	    public void setDialogListener(BuzzDialog.DialogListener listener) {
	        mListenerRef = new WeakReference<BuzzDialog.DialogListener>(listener);
	    }
	    
	    @Override
	    protected Integer doInBackground(String... params) {
	        String url = params[0];
	        
	        Bundle urlParams = HttpUtils.decodeParams(url.substring(url.indexOf("?") + 1));
	        String verifier = urlParams.getString("oauth_verifier");
	        
	        try {
	            mProviderRef.get().retrieveAccessToken(mConsumerRef.get(), verifier);
	            return BuzzDialog.STATUS_OK;
            } catch (Exception e) {
                Log.e("BuzzPlugin", "Error getting access token: " + e.toString());
                return BuzzDialog.STATUS_FAILED;
            }
	    }
	    
	    @Override
	    protected void onPostExecute(Integer status) {
	        switch (status) {
	        case STATUS_OK:
	            SharedPreferences prefs = getContext().getSharedPreferences("buzz_oauth.prefs", Context.MODE_PRIVATE);
	                prefs.edit().putString(Constants.PREF_TOKEN, mConsumerRef.get().getToken()).
	                putString(Constants.PREF_TOKEN_SECRET, mConsumerRef.get().getTokenSecret()).commit();
	                
	            mSpinnerRef.get().dismiss();
	            mDialogRef.get().dismiss();
	            mWebViewRef.get().clearCache(true);
	            
	            if (mListenerRef != null) {
	                mListenerRef.get().onComplete();
	            }
	            
	            break;
	        case STATUS_FAILED:
	            /* wtf is wrong with you. don't you ever fail. */
	            break;
	        default:
	            Log.wtf(Constants.LOG_TAG, "You should never see this. Ever.");
	        }
	    }
	}
	
	private class BuzzWebViewClient extends WebViewClient {
		@Override
		public boolean shouldOverrideUrlLoading(WebView view, String url) {
		    if (url.startsWith("http://slidescreenbuzz.com/callback")) {
		        AccessTokenTask task = new AccessTokenTask(BuzzDialog.this, view, mSpinner, mConsumer, mProvider);
		        task.setDialogListener(mListener);
		        task.execute(url);
		        
		        return true;
		    }
		    		    
			return false;
		}
		
		@Override
		public void onPageStarted(WebView view, String url, Bitmap favicon) {
			super.onPageStarted(view, url, favicon);
			mSpinner.show();
		}
		
		@Override
		public void onPageFinished(WebView view, String url) {
			super.onPageFinished(view, url);
			mSpinner.hide();
		}
	}
	
	public interface DialogListener {
		public void onComplete();
		
		public void onError();
		
		public void onCancel();
	}
}
